#include "str_list.h"

#include <string.h>
#include <stdio.h>

int
li_str_create(li_str ** str)
{
	(*str) = malloc(sizeof(snode));
	memset(*str, 0, sizeof(snode));

	return 0;
}

int
li_str_substr(const li_str * a, size_t i, size_t j, li_str ** str)
{
	if (i >= j) {
		return ERR_INDEX;
	}

	for (size_t ii = 0; ii < i; ++ii) {
		if (a) {
			a = a->next;
		}
		else {
			return ERR_INDEX;
		}
	}

	if (!a) {
		return ERR_INDEX;
	}

	li_str *** p = &str;
	for (size_t jj = 0; jj < j - i; ++jj) {
		if (a) {
			li_str_create(str);
			(*str)->data = a->data;
			str = &(*str)->next;
			a = a->next;
		}
		else {
			li_str_release(**p);
			return ERR_INDEX;
		}
	}

	return 0;
}

int
li_str_release(li_str * str)
{
	snode * a = str;
	snode * b = a->next;
	for (; a; a = b, b = b ? b->next : 0) {
		free(a);
	}

	return 0;
}

size_t
li_str_len(const li_str * s)
{
	size_t len = 0;
	for (; s; s = s->next, ++len) {}
	return len;
}

int
li_str_assign(li_str ** s, const char * p)
{
	snode ** node = s;

	for (; *p; ++p) {
		li_str_create(node);
		(*node)->data = *p;
		node = &(*node)->next;
	}

	return 0;
}

int
li_str_copy(li_str ** str, const li_str * a)
{
	snode ** node = str;

	for (; a; a = a->next) {
		li_str_create(node);
		(*node)->data = a->data;
		node = &(*node)->next;
	}

	return 0;
}

int
li_str_eq(const li_str * s, const li_str * t)
{
	for (; s && t; s = s->next, t = t->next) {
		if (s->data != t->data) {
			return ERR_NEQ;
		}
	}

	return (s == t) ? 0 : ERR_NEQ;
}

int
li_str_cat(li_str * str, const li_str * a)
{
	for (; str->next; str = str->next) {}

	snode ** node = &str->next;

	for (; a; a = a->next) {
		li_str_create(node);
		(*node)->data = a->data;
		node = &(*node)->next;
	}

	return 0;
}

int
li_str_insert(li_str * str, size_t i, const li_str * a)
{
	snode node;
	node.next = str;

	str = &node;

	for (size_t ii = 0; ii < i; ++ii) {
		if (str) {
			str = str->next;
		}
		else {
			return ERR_INDEX;
		}
	}

	snode * temp = str->next;

	li_str ** s= &str->next;
	for (; a; a = a->next) {
		li_str_create(s);
		(*s)->data = a->data;
		s = &(*s)->next;
	}

	*s = temp;

	return 0;
}

int
li_str_del(li_str * str, size_t i, size_t j)
{
	if (i >= j) {
		return ERR_INDEX;
	}
	snode node;
	node.next = str;

	str = &node;

	for (size_t ii = 0; ii < i; ++ii) {
		if (str) {
			str = str->next;
		}
		else {
			return ERR_INDEX;
		}
	}

	for (size_t jj = 0; jj < j - i; ++jj) {
		if (str->next) {
			snode * node = str->next;
			str->next = node->next;
			node->next = 0;
			li_str_release(node);
		}
		else {
			break;
		}
	}

	return 0;
}

int
li_str_replace(li_str * str, size_t i, size_t j, const li_str * a)
{
	if (i >= j) {
		return ERR_INDEX;
	}

	snode node;
	node.next = str;

	str = &node;

	for (size_t ii = 0; ii < i; ++ii) {
		if (str) {
			str = str->next;
		}
		else {
			return ERR_INDEX;
		}
	}

	for (size_t jj = 0; jj < j - i; ++jj) {
		if (str->next) {
			snode * node = str->next;
			str->next = node->next;
			node->next = 0;
			li_str_release(node);
		}
		else {
			break;
		}
	}

	snode * temp = str->next;

	li_str ** p = &str->next;
	for (; a; a = a->next) {
		li_str_create(p);
		(*p)->data = a->data;
		p = &(*p)->next;
	}

	*p = temp;

	return 0;
}

int
li_str_display(const li_str * s)
{
	printf("_");
	for ( ; s; s = s->next) {
		printf("%c", s->data);
	}
	printf("_\n\n");

	return 0;
}

